package com.zzz.thrift.gateway.service;

import org.apache.thrift.TException;
import org.apache.thrift.protocol.*;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ThriftMessageUtils {

    public static void wirteData(TProtocol out, List<ProxyStruct> outDatas) throws TException {
        out.writeStructBegin(new TStruct(""));
        for (ProxyStruct outData : outDatas) {
            TField field = outData.field;
            Object value = outData.value;
            out.writeFieldBegin(field);

            switch (field.type) {
                case TType.VOID:
                    break;
                case TType.BOOL:
                    out.writeBool((boolean) value);
                    break;
                case TType.BYTE:
                    out.writeByte((byte) value);
                    break;
                case TType.DOUBLE:
                    out.writeDouble((double) value);
                    break;
                case TType.I16:
                    out.writeI16((short) value);
                    break;
                case TType.I32:
                    out.writeI32((int) value);
                    break;
                case TType.I64:
                    out.writeI64((long) value);
                    break;
                case TType.STRING:
                    out.writeString((String) value);
                    break;
                case TType.STRUCT:
                    wirteData(out, (List<ProxyStruct>) value);
                    break;
                case TType.MAP:
                    //out.writeMapBegin((TMap)value);
                    //out.writeMapEnd();
                    break;
                case TType.SET:
                    //out.writeSetBegin((TSet)value);
                    //out.writeSetEnd();
                    break;
                case TType.LIST:
                    out.writeListBegin(new org.apache.thrift.protocol.TList(org.apache.thrift.protocol.TType.STRUCT, ((List<List<ProxyStruct>>) value).size()));
                    List<List<ProxyStruct>> lists = (List<List<ProxyStruct>>) value;
                    for(List<ProxyStruct> list : lists) {
                        wirteData(out, list);
                    }
                    out.writeListEnd();
                    break;
                case TType.ENUM:
                    break;
                default:
            }

            out.writeFieldEnd();
        }
        out.writeFieldStop();
        out.writeStructEnd();
    }

    public static List<ProxyStruct> readData(TProtocol in) throws TException {
        List<ProxyStruct> inDatas = new ArrayList<>();
        TField schemeField;
        in.readStructBegin();
        while (true) {
            schemeField = in.readFieldBegin();
            if (schemeField.type == TType.STOP) {
                break;
            }
            ProxyStruct inData = null;

            switch (schemeField.type) {
                case TType.VOID:
                    TProtocolUtil.skip(in, schemeField.type);
                    break;
                case TType.BOOL:
                    inData = new ProxyStruct(schemeField, in.readBool());
                    break;
                case TType.BYTE:
                    inData = new ProxyStruct(schemeField, in.readByte());
                    break;
                case TType.DOUBLE:
                    inData = new ProxyStruct(schemeField, in.readDouble());
                    break;
                case TType.I16:
                    inData = new ProxyStruct(schemeField, in.readI16());
                    break;
                case TType.I32:
                    inData = new ProxyStruct(schemeField, in.readI32());
                    break;
                case TType.I64:
                    inData = new ProxyStruct(schemeField, in.readI64());
                    break;
                case TType.STRING:
                    inData = new ProxyStruct(schemeField, in.readString());
                    System.out.println("String-->" + inData.value);
                    break;
                case TType.STRUCT:
                    inData = new ProxyStruct(schemeField, readData(in));
                    break;
                case TType.MAP:
                    Map<String, Object> map = new HashMap<>();
                    TMap tMap = in.readMapBegin();
                    //inData = new ProxyStruct(schemeField, in.readMapBegin());
                    /**
                     *  readMapBegin返回的TMap对象有3个字段
                     * keyType，valueType，size，没错就是map的key的类型，value的类型，map的大小
                     * 从0到size累计循环的按类型读取key和读取value，构造一个hashmap就可以了
                     */
                    //in.readMapEnd();
                    break;
                case TType.SET:
                    //inData = new ProxyStruct(schemeField, in.readSetBegin());
                    //同理MAP类型
                    //in.readSetEnd();
                    break;
                case TType.LIST:
                    TList tList = in.readListBegin();
                    List<List<ProxyStruct>> list = new ArrayList<>();
                    for (int i = 0; i < tList.size; ++i) {
                        list.add(readData(in));
                    }
                    inData = new ProxyStruct(schemeField, list);
                    //同理MAP类型
                    in.readListEnd();
                    break;
                case TType.ENUM:
                    //Enum类型传输时是个i32
                    TProtocolUtil.skip(in, schemeField.type);
                    break;
                default:
                    TProtocolUtil.skip(in, schemeField.type);
            }
            if (inData != null) inDatas.add(inData);
            in.readFieldEnd();
        }
        in.readStructEnd();
        return inDatas;
    }
}
